﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MaxLeaf.Common;
using System.Data;
using MaxLeaf.DB;
namespace MaxLeaf.DAL
{
    public interface ICheckLog
    {
        bool CheckLog(ServerInfo server, System.Data.DataRowView drv);
    }

    /// <summary>
    /// checklog操作基类
    /// </summary>
    public class BaseDALBuilder : ICheckLog
    {
               
        
        

        private K2K.IDALAction _k2kDAL = null;
        private K2W.IDALAction _k2wDAL = null;
        private W2K.IDALAction _w2kDAL = null;
        private Web2SCP.IDALAction _web2scpDAL = null;
        private SCP2Web.IDALAction _scp2webDAL = null;



        protected K2K.IDALAction K2KDAL
        {
            set
            {
                _k2kDAL = value;
            }
        }
        protected K2W.IDALAction K2WDAL
        {
            set
            {

                _k2wDAL = value;
               
            }
        }
        protected W2K.IDALAction W2KDAL
        {
            set
            {

                _w2kDAL = value;

            }
        }
        protected Web2SCP.IDALAction Web2SCPDAL
        {
            set
            {

                _web2scpDAL = value;

            }
        }
        protected SCP2Web.IDALAction SCP2WebDAL
        {
            set
            {

                _scp2webDAL = value;

            }
        }
        public BaseDALBuilder()
        {
            
            
        }


        public bool CheckLog(ServerInfo orgServer, System.Data.DataRowView drvLog)
        {
            LogManager.Debug(string.Format("begin CheckLog {0}", orgServer));
            //源数据是否需要分发
            if (!ValidCheckOrgData(orgServer, drvLog))
            {
                LogManager.Debug(string.Format("ValidCheckOrgData=false {0}", orgServer));
                return  true;
            }
        
            LogStatus iLogStatus = (LogStatus)CvtFunc.ToInt(drvLog[DEL.LogDEL.LogStatus]);
            LogManager.Debug(string.Format(" {0}   {1}", orgServer, iLogStatus));
            //得到唯一需要运行的数据库，如果没有就全部
            string strK3DestServerDBName = GetK3DestServerDBName(orgServer,drvLog);
            string strWebDestServerDBName = GetWebDestServerDBName(orgServer, drvLog);

            List<ServerInfo> destServers = ServerInfo.GetServers(ServerType.All, CvtFunc.ToString(drvLog[DEL.LogDEL.UpdateMode]));
            bool blnRT = true;
            foreach (ServerInfo destServer in destServers)
            {

                if (destServer.MasterDB)
                {
                    //访问主账套
                    if (strK3DestServerDBName.Length == 0 || strK3DestServerDBName.Equals(destServer.Database, StringComparison.InvariantCultureIgnoreCase))
                    {
                        DoAction(drvLog, iLogStatus, ref blnRT, orgServer, destServer);
                    }
                    if (destServer.CityDBs != null && destServer.CityDBs.Count > 0)
                    {
                        foreach (ServerInfo cityServer in ServerInfo.GetCityServers(destServer, new DBAccess(destServer).GetAllServers()))
                        {
                            //访问分账套
                            if (strK3DestServerDBName.Length == 0 || strK3DestServerDBName.Equals(cityServer.Database, StringComparison.InvariantCultureIgnoreCase))
                            {
                                DoAction(drvLog, iLogStatus, ref blnRT, orgServer, cityServer);
                            }
                        }
                    }
                }
                else
                {

                    if (strWebDestServerDBName.Length == 0 || strWebDestServerDBName.Equals(destServer.Database, StringComparison.InvariantCultureIgnoreCase))
                    {
                        DoAction(drvLog, iLogStatus, ref blnRT, orgServer, destServer);
                    }
                }
            }
            return blnRT;
        }

        protected virtual  string GetK3DestServerDBName(ServerInfo orgServer, DataRowView drvLog)
        {
            return string.Empty;
        }
        protected virtual string GetWebDestServerDBName(ServerInfo orgServer, DataRowView drvLog)
        {
            return string.Empty;
        }

        private void DoAction(System.Data.DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer)
        {
            LogManager.Debug(string.Format(" DoAction {0}   {1}", orgServer, destServer));
            //源==目标
            if (orgServer.Type == destServer.Type && orgServer.Database == destServer.Database)
            {
                return ;
            }

            if (orgServer.Type == ServerType.K3 && destServer.Type == ServerType.K3)
            {
                DoAction_K2K(drvLog, iLogStatus, ref   blnRT, orgServer, destServer,_k2kDAL);
            }
            else if (orgServer.Type == ServerType.K3 && destServer.Type == ServerType.Web)
            {
                DoAction_K2W(drvLog, iLogStatus, ref   blnRT, orgServer, destServer, _k2wDAL);
                
            }
            else if (orgServer.Type == ServerType.Web && destServer.Type == ServerType.K3)
            {
                DoAction_W2K(drvLog, iLogStatus, ref   blnRT, orgServer, destServer, _w2kDAL);
                
            }
            else if (orgServer.Type == ServerType.Web && destServer.Type == ServerType.SCP)
            {
                DoAction_Web2SCP(drvLog, iLogStatus, ref   blnRT, orgServer, destServer, _web2scpDAL);

            }
            else if (orgServer.Type == ServerType.SCP && destServer.Type == ServerType.Web)
            {
                DoAction_SCP2Web(drvLog, iLogStatus, ref   blnRT, orgServer, destServer, _scp2webDAL);

            }
 
            

        }
        private void DoAction_SCP2Web(DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer, SCP2Web.IDALAction dal)
        {
            if (dal == null)
            {
                //目标不需要操作
                LogManager.Debug(string.Format(" 目标不需要操作 {0}   {1}", orgServer, destServer));
                return;
            }

            //是否需要分发当前目标


            if (!ValidCheck(orgServer, destServer, drvLog))
            {
                LogManager.Debug(string.Format(" 不需要分发当前目标 {0}   {1}", orgServer, destServer));
                return;
            }


            using (DBAccess dbOrgSCPCon = new DBAccess(orgServer), dbDestWebReadCon = new DBAccess(destServer), dbDestWebWriteCon = new DBAccess(destServer.WriteDB))
            {
                try
                {
                    //LogManager.Debug(dbDestWebReadCon.Connection.ConnectionString);
                    ClearWebKeyMapDict(dbDestWebWriteCon);
                    dbDestWebWriteCon.BeginTrans();

                    if (iLogStatus == LogStatus.Delete)
                    {
                        dal.Delete(dbOrgSCPCon, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Add)
                    {
                        dal.Add(dbOrgSCPCon, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Update)
                    {
                        dal.Update(dbOrgSCPCon, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }


                    CommitWebKeyMapDict(dbOrgSCPCon);

                    dbDestWebWriteCon.CommitTrans();

                    if (orgServer.MasterDB)
                    {
                        //记录分发过的数据库，下次直接跳过
                        LogCompleted(dbOrgSCPCon, destServer, drvLog);
                    }
                }
                catch (Exception ex)
                {
                    dbDestWebWriteCon.RollbackTrans();
                    LogManager.Error(ex);
                    blnRT = false;

                    RollbackWebKeyMapDict(dbOrgSCPCon);
                }

            }
        }

        private void DoAction_Web2SCP(DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer, Web2SCP.IDALAction dal)
        {
            if (dal == null)
            {
                //目标不需要操作
                LogManager.Debug(string.Format(" 目标不需要操作 {0}   {1}", orgServer, destServer));
                return;
            }

            //是否需要分发当前目标


            if (!ValidCheck(orgServer, destServer, drvLog))
            {
                LogManager.Debug(string.Format(" 不需要分发当前目标 {0}   {1}", orgServer, destServer));
                return;
            }


            using (DBAccess dbOrgWebReadCon = new DBAccess(orgServer), dbOrgWebWriteCon = new DBAccess(orgServer.WriteDB), dbDestSCPCon = new DBAccess(destServer))
            {
                try
                {
                    //LogManager.Debug(dbOrgWebReadCon.Connection.ConnectionString);
                    ClearWebKeyMapDict(dbOrgWebWriteCon);
                    dbDestSCPCon.BeginTrans();

                    if (iLogStatus == LogStatus.Delete)
                    {
                        dal.Delete(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestSCPCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Add)
                    {
                        dal.Add(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestSCPCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Update)
                    {
                        dal.Update(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestSCPCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }


                    CommitWebKeyMapDict(dbOrgWebWriteCon);

                    dbDestSCPCon.CommitTrans();

                    if (orgServer.MasterDB)
                    {
                        //记录分发过的数据库，下次直接跳过
                        LogCompleted(dbOrgWebWriteCon, destServer, drvLog);
                    }
                }
                catch (Exception ex)
                {
                    dbDestSCPCon.RollbackTrans();
                    LogManager.Error(ex);
                    blnRT = false;

                    RollbackWebKeyMapDict(dbOrgWebWriteCon);
                }

            }
        }

        private void DoAction_W2K(DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer, W2K.IDALAction dal)
        {
            if (dal == null)
            {
                //目标不需要操作
                LogManager.Debug(string.Format(" 目标不需要操作 {0}   {1}", orgServer, destServer));
                return;
            }

            //是否需要分发当前目标


            if (!ValidCheck(orgServer, destServer, drvLog))
            {
                LogManager.Debug(string.Format(" 不需要分发当前目标 {0}   {1}", orgServer, destServer));
                return;
            }

 
            using (DBAccess dbOrgWebReadCon = new DBAccess(orgServer), dbOrgWebWriteCon = new DBAccess(orgServer.WriteDB), dbDestK3Con = new DBAccess(destServer))
            {
                try
                {
                    //LogManager.Debug(dbOrgWebReadCon.Connection.ConnectionString);

                    ClearWebKeyMapDict(dbOrgWebWriteCon);
                    dbDestK3Con.BeginTrans();

                    if (iLogStatus == LogStatus.Delete)
                    {
                        dal.Delete(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Add)
                    {
                        dal.Add(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Update)
                    {
                        dal.Update(dbOrgWebReadCon, dbOrgWebWriteCon, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }


                    CommitWebKeyMapDict(dbOrgWebWriteCon);

                    dbDestK3Con.CommitTrans();

                    if (orgServer.MasterDB)
                    {
                        //记录分发过的数据库，下次直接跳过
                        LogCompleted(dbOrgWebWriteCon, destServer, drvLog);
                    }
                }
                catch (Exception ex)
                {
                    dbDestK3Con.RollbackTrans();
                    LogManager.Error(ex);
                    blnRT = false;

                    RollbackWebKeyMapDict(dbOrgWebWriteCon);
                }

            }
        }

        private void DoAction_K2W(DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer, K2W.IDALAction dal)
        {
            if (dal == null)
            {
                //目标不需要操作
                LogManager.Debug(string.Format(" 目标不需要操作 {0}   {1}", orgServer, destServer));
                return;
            }

            //是否需要分发当前目标


            if (!ValidCheck(orgServer, destServer, drvLog))
            {
                LogManager.Debug(string.Format(" 不需要分发当前目标 {0}   {1}", orgServer, destServer));
                return;
            }


            using (DBAccess dbOrgK3Con = new DBAccess(orgServer), dbDestWebReadCon = new DBAccess(destServer), dbDestWebWriteCon = new DBAccess(destServer.WriteDB))
            {
                try
                {
                    //LogManager.Debug(dbDestWebReadCon.Connection.ConnectionString);

                    ClearWebKeyMapDict(dbDestWebWriteCon);
                    dbDestWebWriteCon.BeginTrans();

                    if (iLogStatus == LogStatus.Delete)
                    {
                        dal.Delete(dbOrgK3Con, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Add)
                    {
                        dal.Add(dbOrgK3Con, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Update)
                    {
                        dal.Update(dbOrgK3Con, dbDestWebReadCon, dbDestWebWriteCon, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }


                    CommitWebKeyMapDict(dbOrgK3Con);

                    dbDestWebWriteCon.CommitTrans();

                    if (orgServer.MasterDB)
                    {
                        //记录分发过的数据库，下次直接跳过
                        LogCompleted(dbOrgK3Con, destServer, drvLog);
                    }
                }
                catch (Exception ex)
                {
                    dbDestWebWriteCon.RollbackTrans();
                    LogManager.Error(ex);
                    blnRT = false;

                    RollbackWebKeyMapDict(dbOrgK3Con);
                }

            }
        }

        private void DoAction_K2K(DataRowView drvLog, LogStatus iLogStatus, ref bool blnRT, ServerInfo orgServer, ServerInfo destServer, K2K.IDALAction dal)
        {
            if (dal == null)
            {
                //目标不需要操作
                LogManager.Debug(string.Format(" 目标不需要操作 {0}   {1}", orgServer, destServer));
                return;
            }

            //是否需要分发当前目标


            if (!ValidCheck(orgServer, destServer, drvLog))
            {
                LogManager.Debug(string.Format(" 不需要分发当前目标 {0}   {1}", orgServer, destServer));
                return;
            }


            using (DBAccess dbOrgK3Con = new DBAccess(orgServer), dbDestK3Con = new DBAccess(destServer))
            {
                try
                {
                    ClearWebKeyMapDict(dbOrgK3Con);
                    dbDestK3Con.BeginTrans();

                    if (iLogStatus == LogStatus.Delete)
                    {
                        dal.Delete(dbOrgK3Con, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Add)
                    {
                        dal.Add(dbOrgK3Con, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }
                    else if (iLogStatus == LogStatus.Update)
                    {
                        dal.Update(dbOrgK3Con, dbDestK3Con, CvtFunc.ToString(drvLog[DEL.LogDEL.KeyValue]));
                    }


                    CommitWebKeyMapDict(dbOrgK3Con);

                    dbDestK3Con.CommitTrans();

                    if (orgServer.MasterDB)
                    {
                        //记录分发过的数据库，下次直接跳过
                        LogCompleted(dbOrgK3Con, destServer, drvLog);
                    }
                }
                catch (Exception ex)
                {
                    dbDestK3Con.RollbackTrans();
                    LogManager.Error(ex);
                    blnRT = false;

                    RollbackWebKeyMapDict(dbOrgK3Con);
                }

            }
        }

        private void CommitWebKeyMapDict(DBAccess dbOrgCon)
        {
            if (dbOrgCon.ServerType == ServerType.Web)
            {
                foreach (WebKeyMapDict map in dbOrgCon.WebKeyMap)
                {
                    SaveKeyMap(dbOrgCon, map);
                }

                ClearWebKeyMapDict(dbOrgCon);
            }
        }

        protected void SaveKeyMap(DBAccess dbOrgWebCon, WebKeyMapDict map)
        {
            string strCheckSql = string.Format(@"select * from {0} where   {1}={2}OrgKeyValue", map.TableName, map.WebMapKeyFieldName, dbOrgWebCon.ParamSign);
            string strInsertSql = string.Format(@"insert into {0}({1},{2}) 
                values({3}OrgKeyValue,{3}DestKeyValue)",
                map.TableName, map.WebMapKeyFieldName, map.K3MapKeyFieldName, dbOrgWebCon.ParamSign);
            string strUpdateSql = string.Format(@"update {0}  set  {2}={3}DestKeyValue  where {1}={3}OrgKeyValue",
                map.TableName, map.WebMapKeyFieldName, map.K3MapKeyFieldName, dbOrgWebCon.ParamSign);

            KeyValuePair<string, IDataParameter[]> kvpMap = dbOrgWebCon.CreateCondParam(new Dictionary<string, object> {
                 { "OrgKeyValue", map.WebKeyValue }
                , { "DestKeyValue", map.K3KeyValue }
            });
            DataRow drCheck = dbOrgWebCon.GetDataFirstRow(strCheckSql, kvpMap.Value);
            if (drCheck == null)
            {
                kvpMap = dbOrgWebCon.CreateCondParam(new Dictionary<string, object> {
                     { "OrgKeyValue", map.WebKeyValue }
                    , { "DestKeyValue", map.K3KeyValue }
                });
                dbOrgWebCon.ExecuteSql(strInsertSql, kvpMap.Value);
            }
            else if (!CvtFunc.ToString(drCheck[map.K3MapKeyFieldName]).Equals(map.K3KeyValue, StringComparison.InvariantCultureIgnoreCase))
            {
                kvpMap = dbOrgWebCon.CreateCondParam(new Dictionary<string, object> {
                     { "OrgKeyValue", map.WebKeyValue }
                    , { "DestKeyValue", map.K3KeyValue }
                });
                dbOrgWebCon.ExecuteSql(strUpdateSql, kvpMap.Value);
            }
        }

        private void RollbackWebKeyMapDict(DBAccess dbOrgCon)
        {
            if (dbOrgCon.ServerType == ServerType.Web)
            {
                //foreach (WebKeyMapDict map in dbOrgCon.WebKeyMap)
                //{
                //    DeleteKeyMap(dbOrgCon, map);
                //}

                ClearWebKeyMapDict( dbOrgCon);
            }
        }

        private void DeleteKeyMap(DBAccess dbOrgWebCon, WebKeyMapDict map)
        {
            string strSql = string.Format(@"delete from {0}  where  {1}={2}OrgKeyValue",
                map.TableName, map.WebMapKeyFieldName,  dbOrgWebCon.ParamSign);

            KeyValuePair<string, IDataParameter[]> kvpMap = dbOrgWebCon.CreateCondParam(new Dictionary<string, object> {
                 { "OrgKeyValue", map.WebKeyValue }
                , { "DestKeyValue", map.K3KeyValue }
            });
            dbOrgWebCon.ExecuteSql(strSql, kvpMap.Value);

        }
        


        private void ClearWebKeyMapDict(DBAccess dbOrgCon)
        {
            if (dbOrgCon.ServerType == ServerType.Web)
            {
                dbOrgCon.WebKeyMap.Clear();
            }
            
        }


        protected virtual bool ValidCheckOrgData(ServerInfo orgServer , DataRowView drvLog)
        {
             
            return true;
        }

        protected virtual bool ValidCheck(ServerInfo orgServer, ServerInfo destServer, DataRowView drvLog)
        {
             
            return true;
        }

        private void LogCompleted(DBAccess dbOrgCon, ServerInfo destServer, DataRowView drvLog)
        {
//            string strSql = @"
//            if not exists(select * from k3_mLogComplete where RecID=@RecID  and DBName=@DBName)
//            begin
//            insert into k3_mLogComplete(RecID,DBName) values(@RecID,@DBName)
//            end";
//            KeyValuePair<string, IDataParameter[]> kvp = dbOrgCon.CreateCondParam(new Dictionary<string, object>() { { "RecID", drvLog[DEL.LogDEL.RecId] }, { "DBName", destServer.ToString() } });
//            dbOrgCon.ExecuteSql(strSql,kvp.Value);
        }
        

        

       

    }
}
